home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / MacGzip 1.0 / source / Mac / MacIO.c < prev    next >
Text File  |  1995-09-28  |  20KB  |  863 lines

  1. /*
  2.  * MacIO.c
  3.  *
  4.  * SPDsoft, August 19, 1995
  5.  * A minimal, non standard Mac IO implementation
  6.  *
  7.  *        Secuential read/write, ascii/binary/macbinary, buffered IO
  8.  *
  9.  * Sept, 1995: Multiple bug fixes.
  10.  */
  11.  
  12.  
  13. /*
  14.  * open:
  15.  *            - in MacBinary w mode, actual open is delayed to write/close
  16.  *            - in MacBinary w mode, if file is not MB, fs is used; otherwise
  17.  *                MB name is copied to fs;
  18.  *
  19.  *            - In any w mode, output file must not exist
  20.  */
  21.  
  22. /*
  23.  * fd_table[].new is used only externally
  24.  * You can safely remove all references
  25.  */
  26.  
  27. #include <errno.h>
  28.  
  29. #include <Files.h>
  30. #include <Memory.h>
  31.  
  32. #include "MacBinary.h"
  33. #include "MacIO.h"
  34.  
  35. #include "GzErrors.h"
  36.  
  37. #ifndef MIN
  38. #define MIN(a,b)    ( ((a)<(b)) ? (a) : (b) )
  39. #endif
  40.  
  41. #ifndef PStrCpy
  42. #define    PStrCpy(a,b)        BlockMove((b), (a), *(b) + 1 )
  43. #endif
  44.  
  45. OSType                    DefCreator = 'Gzip';
  46. OSType                    DefType = '\?\?\?\?';
  47. fildes                    fd_table[MIO_MAX_FILES];
  48. int                        fd_busy[MIO_MAX_FILES] = {    0, 0 };
  49.  
  50. static int        fs_MBflush( int fd );
  51. static int        MyBlockMove( char *src, char *dst, Size n, char c1, char c2 );
  52. static OSErr    OpenPlainFromMB( int fd );
  53. static int        CatInfoToStat (CInfoPBRec *info, struct stat *buf);
  54. static void        SanitizeName (Str255 name);
  55.  
  56. /*
  57.  * these are in gzip.c You can delete them safely (along with the calls)
  58.  * for other applications
  59.  */
  60.  
  61. extern FSSpec    ofs;
  62. extern char        ofname[];
  63. extern int        decompress;
  64. extern OSErr    MakeOFSSpec( FSSpec *fs , Str255 prompt );
  65.  
  66. extern void        SetMMString( const char *fmt, ... );
  67.  
  68. /* end of gzip options
  69.  */
  70. extern int DoError( int ErrType, int ErrSever,const char *, ...);
  71.  
  72. /******************************************************************************
  73.  * functions
  74.  */
  75. #define    ExitErr(a)        { if ((a) != noErr ) { errno = (a); return -1; } }
  76.  
  77. /*
  78.  *    Upon successful completion, the file descriptor is returned.
  79.  *    Otherwise, a value of -1 is returned and errno is set to indicate the
  80.  *    error.
  81.  */
  82. int fs_open( FSSpec *fs, int mode, ...)
  83. {
  84.     int                    i;
  85.     OSErr                err;
  86.     
  87.     
  88.     if (( fs == nil )||(mode & OM_RDWR))/* not supported */
  89.     {
  90.         errno = EFAULT;
  91.         return -1;
  92.     }
  93.     
  94.     for ( i = 0; i< MIO_MAX_FILES; i++ )
  95.         if (fd_busy[i] == 0)
  96.             break;
  97.     
  98.     if ( i == MIO_MAX_FILES )
  99.     {
  100.         errno = ENFILE;
  101.         return -1;
  102.     }
  103.             
  104.     fd_table[i].fsomode = mode;
  105.     
  106.     fd_table[i].mode = MIO_BINARY;
  107.     if ( mode & OM_TEXT ) fd_table[i].mode = MIO_ASCII;
  108.     if ( mode & OM_MACBINARY ) fd_table[i].mode = MIO_MACBIN;
  109.  
  110.     if ( mode & OM_WRONLY )
  111.     {
  112.         fd_table[i].omode    = OM_WRONLY;
  113.         fd_table[i].dref    = 0;
  114.         fd_table[i].rref    = 0;
  115.         fd_table[i].pos        = 0L;
  116.         fd_table[i].len        = 0L;
  117.         fd_table[i].blen    = 0;
  118.         fd_table[i].bstart    = fd_table[i].buffer;
  119.         fd_table[i].deof    = 0;
  120.         fd_table[i].reof    = 0;
  121.  
  122.         fd_table[i].new        = 0;
  123.         fd_table[i].fs        = *fs;
  124.  
  125.         if (fd_table[i].mode != MIO_MACBIN)
  126.         {
  127.             err = FSpCreate(fs, DefCreator, DefType, 0);
  128.             ExitErr(err);
  129.             
  130.             fd_table[i].new        = 1;
  131.             
  132.             if ( noErr != (err = FSpOpenDF(fs, fsWrPerm, &fd_table[i].dref)))
  133.             {
  134.                 fd_table[i].dref = 0;
  135.                 FSpDelete(fs);
  136.                 errno = err;
  137.                 return -1;
  138.             }
  139.         }
  140.         else
  141.         {
  142.             fd_table[i].bstart = (char *)&fd_table[i].header;
  143.         }
  144.         /* we can't open nothing in MacBinary Mode */
  145.     }
  146.     else /* OM_RDONLY */
  147.     {
  148.         err = MBHeaderFromFSSpec( fs, &fd_table[i].start, (MBIIHeader *) &fd_table[i].buffer);
  149.         
  150.         ExitErr(err);
  151.                 
  152.         fd_table[i].omode    = OM_RDONLY;
  153.         fd_table[i].dref    = 0;
  154.         fd_table[i].rref    = 0;
  155.         fd_table[i].pos        = 0L;
  156.         fd_table[i].len        = 0L;
  157.         fd_table[i].blen    = 0;
  158.         fd_table[i].bstart    = fd_table[i].buffer;
  159.         fd_table[i].deof    = 0;
  160.         fd_table[i].reof    = 0;
  161.         
  162.         fd_table[i].new        = 0;
  163.         fd_table[i].fs        = *fs;
  164.         
  165.         err = FSpOpenDF(fs, fsRdPerm, &fd_table[i].dref);
  166.         ExitErr(err);
  167.         
  168.         if (fd_table[i].mode == MIO_MACBIN)
  169.         {
  170.             fd_table[i].blen = sizeof(MBIIHeader);    
  171.             fd_table[i].len = sizeof(MBIIHeader) + fd_table[i].start.dlen + fd_table[i].start.rlen;    
  172.             if ( noErr != (err = FSpOpenRF(fs, fsRdPerm, &fd_table[i].rref)))
  173.             {
  174.                 FSClose(fd_table[i].dref); fd_table[i].dref = fd_table[i].rref = 0;
  175.                 errno = err;
  176.                 return -1;
  177.             }
  178.         }
  179.         else
  180.         {
  181.             fd_table[i].len = fd_table[i].start.dlen;
  182.             fd_table[i].start.rlen = 0;
  183.         }
  184.     }
  185.     
  186.     fd_busy[i] = 1;
  187.     return i;
  188. }
  189.  
  190.  
  191. int fs_close(int fd)
  192. {
  193.     ParamBlockRec    pb;
  194.     OSErr            err = noErr;
  195.     long            count = 0;
  196.     Boolean            SetInfo;
  197.     
  198.     if (( 0 > fd ) || ( fd >= MIO_MAX_FILES) || (fd_busy[fd] == 0))
  199.     {
  200.         errno = EBADF;
  201.         return -1;
  202.     }
  203.     
  204.     fd_busy[fd] = 0;
  205.  
  206.     if ( fd_table[fd].omode != OM_RDONLY ) /* flush buffer here */
  207.     {
  208.         if (fd_table[fd].mode == MIO_MACBIN)
  209.         {
  210.             if (fd_table[fd].pos < 128L ) /* it isn't a MacBinary and is too short */
  211.             {
  212.                 err = OpenPlainFromMB( fd );
  213.             }
  214.             else
  215.             {
  216.                 err = (OSErr) fs_MBflush( fd );
  217.                 
  218.                 if ( err > 0 ) err = 0;
  219.                 
  220.                 ExitErr(err);
  221.                 
  222.                 if ( fd_table[fd].dref != 0 )
  223.                     err = SetEOF( fd_table[fd].dref, fd_table[fd].start.dlen );
  224.     
  225.                 if (( fd_table[fd].rref != 0 )&&(err==noErr))
  226.                     err = SetEOF( fd_table[fd].rref, fd_table[fd].start.rlen );
  227.             }
  228.         }
  229.         ExitErr(err);
  230.         
  231.         if (fd_table[fd].mode != MIO_MACBIN)
  232.         {
  233.             if ( fd_table[fd].blen != 0 )
  234.             {
  235.                 count = (long)fd_table[fd].blen;
  236.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  237.                 ExitErr(err);
  238.             }
  239.             err = SetEOF( fd_table[fd].dref, fd_table[fd].pos ); /* ??? */
  240.         }
  241.         ExitErr(err);
  242.     }
  243.     
  244.     SetInfo =    (fd_table[fd].mode == MIO_MACBIN) &&
  245.                 ( fd_table[fd].omode != OM_RDONLY ) &&
  246.                 ( fd_table[fd].dref != 0 ) &&
  247.                 ( fd_table[fd].rref != 0 ) ;
  248.                 
  249.     
  250.     if ( fd_table[fd].dref != 0 )
  251.     {
  252.         if ( fd_table[fd].omode != OM_RDONLY )
  253.         {
  254.             pb.ioParam.ioCompletion = 0;
  255.             pb.ioParam.ioRefNum = fd_table[fd].dref;
  256.             PBFlushFile(&pb,FALSE);
  257.         }
  258.             
  259.         err = FSClose(fd_table[fd].dref);
  260.         fd_table[fd].dref = 0;
  261.     }    
  262.     if (( fd_table[fd].rref != 0 )&&(err==noErr))
  263.     {
  264.         if ( fd_table[fd].omode != OM_RDONLY )
  265.         {
  266.             pb.ioParam.ioCompletion = 0;
  267.             pb.ioParam.ioRefNum = fd_table[fd].rref;
  268.             PBFlushFile(&pb,FALSE);
  269.         }
  270.         err = FSClose(fd_table[fd].rref);
  271.         fd_table[fd].rref = 0;
  272.     }
  273.     
  274.     
  275.     if (SetInfo)
  276.         SetCatInfoFromMBHeader( &fd_table[fd].fs, &fd_table[fd].start, &fd_table[fd].header);
  277.     
  278.     
  279.     ExitErr(err);
  280.     return 0;
  281. }
  282.  
  283. int fs_unlink(FSSpec *fs)
  284. {
  285.     return(FSpDelete(fs));
  286. }
  287.  
  288.  
  289. /*
  290.  * WARNING: This should be size_t, but it is defined as unsigned!
  291.  *
  292.  * fs_read should return always >= 0 or -1
  293.  * On failure, return -1 and set errno to indicate the error
  294.  * We will use mixed errno/OSErr codes (I hope thy will be coherent!)
  295.  */
  296.  
  297. int fs_read(int fd, char *buf, unsigned int n)
  298. {
  299.     OSErr    err = noErr;
  300.     long    count,
  301.             round;
  302.     int        result = 0;
  303.     short    ref;
  304.     
  305.     if (( 0 > fd ) || ( fd >= MIO_MAX_FILES) || (fd_busy[fd] == 0))
  306.     {
  307.         errno = EBADF;
  308.         return -1;
  309.     }
  310.  
  311.     while (( n > 0 ) && (err == noErr))
  312.     {
  313.         if (fd_table[fd].blen == 0)
  314.         {
  315.             if ( fd_table[fd].deof == 0 )
  316.             {
  317.                 ref = fd_table[fd].dref;
  318.             }
  319.             else
  320.             {
  321.                 if ( fd_table[fd].reof == 0 )
  322.                 {
  323.                     ref = fd_table[fd].rref;
  324.                 }
  325.                 else
  326.                 {
  327.                     n = 0;
  328.                     if (result == 0 ) result = -1;
  329.                 }
  330.             }
  331.                 
  332.             if (ref != 0)
  333.             {
  334.                 count = MIO_BUFSIZE;
  335.                 err = FSRead( ref, &count, fd_table[fd].buffer );
  336.  
  337.                 fd_table[fd].blen += (int) count;
  338.                 fd_table[fd].bstart = fd_table[fd].buffer;
  339.  
  340.                 if ( err == eofErr ) /* end of fork reached */
  341.                 {
  342.                     if (fd_table[fd].mode == MIO_MACBIN)
  343.                         if ( 0 != (round = count%128))
  344.                         {
  345.                             count += 128L - round;
  346.                             fd_table[fd].blen += 128 - (int)round;
  347.                         }
  348.                             
  349.                     if ( fd_table[fd].deof == 1 )
  350.                         fd_table[fd].reof = 1;
  351.                     else
  352.                         fd_table[fd].deof = 1;
  353.                         
  354.                     err = noErr;
  355.                 }
  356.             }    
  357.             else
  358.             {    
  359.                 count = 0;
  360.                 err = eofErr;
  361.             }
  362.             errno = err;
  363.         }
  364.         else
  365.         {
  366.             count = MIN( fd_table[fd].blen, (long) n);
  367.             
  368.             if (fd_table[fd].mode == MIO_ASCII)
  369.                 MyBlockMove( fd_table[fd].bstart, buf, (Size) count, 0x0d, 0x0a );
  370.             else
  371.                 BlockMove(    fd_table[fd].bstart, buf, (Size) count );
  372.  
  373.             buf += count;
  374.             fd_table[fd].blen -= (int) count;
  375.             fd_table[fd].pos += count;
  376.             fd_table[fd].bstart += (int) count;
  377.             result += (int) count;
  378.             n -= (int) count;
  379.             
  380.         }
  381.     }
  382.     
  383.     return result;
  384. }
  385.  
  386. /*
  387.  * Por amor al comercio
  388.  * voy a cruzar ese puente
  389.  * Por amor al comercio
  390.  * voy a cuidar ese dolor
  391.  */
  392.  
  393. /*
  394.  * should return n
  395.  * On  failure, return -1 and set errno to indicate the error
  396.  *
  397.  * n == 0 => return 0
  398.  */
  399.  
  400.  
  401.  
  402. int fs_write(int fd, char *buf, unsigned int n)
  403. {
  404.     OSErr    err = noErr;
  405.     long    count;
  406.     int        result = 0;
  407.     
  408.     if (( 0 > fd ) || ( fd >= MIO_MAX_FILES) || (fd_busy[fd] == 0))
  409.     {
  410.         errno = EBADF;
  411.         return -1;
  412.     }
  413.  
  414.     if (fd_table[fd].mode == MIO_MACBIN)
  415.     {
  416.         /* (probably) MacBinary File */
  417.         
  418.         while (( n > 0 ) && (err == noErr))
  419.         {
  420.             if (fd_table[fd].pos < 128L ) /* fill header struct */
  421.             {
  422.                 count                = MIN( (128L - fd_table[fd].pos), (long) n);
  423.                 BlockMove(    buf,    fd_table[fd].bstart, (Size) count );
  424.                 buf                 += count;
  425.                 fd_table[fd].pos    += count;
  426.                 fd_table[fd].bstart    += (int) count;
  427.                 result                += (int) count;
  428.                 n                    -= (int) count;
  429.                 
  430.                 if (fd_table[fd].pos == 128L )
  431.                 {
  432.                     /* validate header */
  433.                     
  434.                     if (PT_File == ValidateMBHeader( &fd_table[fd].start, &fd_table[fd].header, true ))
  435.                     {
  436.                          PStrCpy( fd_table[fd].fs.name, fd_table[fd].start.name );
  437.                          SanitizeName (fd_table[fd].fs.name);
  438.                          
  439.                          
  440. /* macgzip -> */
  441.                         if ( decompress &&    ( ( fd_table[fd].start.rlen != 0 )    ||    ( fd_table[fd].start.dlen != 0 )))
  442.                         {
  443.                             err = MakeOFSSpec( &fd_table[fd].fs , "\pSave Macintosh File:" );
  444.                             ofs = fd_table[fd].fs;
  445.                             ExitErr(err); /* OJO */
  446.                         }
  447. /* <- macgzip */
  448.                          if ( fd_table[fd].start.dlen == 0 )
  449.                          {
  450.                              fd_table[fd].dref = 0;
  451.                              fd_table[fd].deof = 1;
  452.                          }
  453.                          else
  454.                          {
  455.                              if ( noErr == ( err =
  456.                              FSpCreate( &fd_table[fd].fs, fd_table[fd].start.fcreator, fd_table[fd].start.ftype, 0)))
  457.                             {
  458.                                 fd_table[fd].new        = 1;
  459.                                 err = FSpOpenDF( &fd_table[fd].fs, fsWrPerm, &fd_table[fd].dref);
  460.                             }
  461.                             ExitErr(err);
  462.                             
  463.                             if ( 0 != (fd_table[fd].rdlen = fd_table[fd].start.dlen%128))
  464.                                 fd_table[fd].rdlen = fd_table[fd].start.dlen + (128L - fd_table[fd].rdlen);
  465.                             else
  466.                                 fd_table[fd].rdlen = fd_table[fd].start.dlen;
  467.                          }
  468.  
  469.                          if ( fd_table[fd].start.rlen == 0 )
  470.                          {
  471.                              fd_table[fd].rref = 0;
  472.                              fd_table[fd].reof = 1;
  473.                          }
  474.                          else
  475.                          {
  476.                              FSpCreateResFile( &fd_table[fd].fs, fd_table[fd].start.fcreator, fd_table[fd].start.ftype, 0);
  477.                              if ( noErr == ( err = ResError() ))
  478.                             {    
  479.                                 fd_table[fd].new        = 1;
  480.                                 err = FSpOpenRF( &fd_table[fd].fs, fsWrPerm, &fd_table[fd].rref);
  481.                             }    
  482.                             ExitErr(err);
  483.                                 
  484.                             if ( 0 != (fd_table[fd].rrlen = fd_table[fd].start.rlen%128))
  485.                                 fd_table[fd].rrlen = fd_table[fd].start.rlen + (128L - fd_table[fd].rrlen);
  486.                             else
  487.                                 fd_table[fd].rrlen = fd_table[fd].start.rlen;
  488.  
  489.                          }
  490.                              
  491.                     
  492.                         fd_table[fd].bstart = fd_table[fd].buffer;
  493.                     }
  494.                     else
  495.                     {
  496.                         /* header is not valid */
  497.                         /* treat it (right) like a normal file */
  498.  
  499.                         err = OpenPlainFromMB(fd);
  500.                         break;
  501.                     }
  502.                 }
  503.             }
  504.             else /* write data/resource fork */
  505.             {
  506.                 if (fd_table[fd].blen == MIO_BUFSIZE)
  507.                 {
  508.                     err = fs_MBflush( fd );
  509.                     
  510.                     if ( err > 0 ) err = 0;
  511.                     
  512.                     ExitErr(err);
  513.                     
  514.                     
  515.                 }
  516.                 else
  517.                 {
  518.                     count = MIN( (MIO_BUFSIZE-fd_table[fd].blen), (long) n);
  519.                     BlockMove(    buf, fd_table[fd].bstart, (Size) count );
  520.                     buf += (int) count;
  521.                     
  522.                     fd_table[fd].blen += (int) count;
  523.                     fd_table[fd].pos += count;
  524.                     fd_table[fd].bstart += count;
  525.                     result += (int) count;
  526.                     n -= (int) count;
  527.         
  528.                 }
  529.             }
  530.                 
  531.         } /* while n */
  532.     }
  533.  
  534.     ExitErr(err);
  535.     
  536.     if (fd_table[fd].mode != MIO_MACBIN)
  537.     {
  538.         while (( n > 0 ) && (err == noErr))
  539.         {
  540.             if (fd_table[fd].blen == MIO_BUFSIZE)
  541.             {
  542.                 count = fd_table[fd].blen;
  543.                 
  544.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  545.     
  546.                 fd_table[fd].blen = 0;
  547.                 fd_table[fd].bstart = fd_table[fd].buffer;
  548.             }
  549.             else
  550.             {
  551.                 count = MIN( (MIO_BUFSIZE-fd_table[fd].blen), (long) n);
  552.  
  553.                 if (fd_table[fd].mode == MIO_ASCII)
  554.                     MyBlockMove( buf, fd_table[fd].bstart, (Size) count, 0x0a, 0x0d );
  555.                 else
  556.                     BlockMove( buf, fd_table[fd].bstart, (Size) count );
  557.  
  558.                 buf += (int) count;
  559.  
  560.                 fd_table[fd].blen += (int) count;
  561.                 fd_table[fd].pos += count;
  562.                 fd_table[fd].bstart += count;
  563.                 result += (int) count;
  564.                 n -= (int) count;
  565.     
  566.             }
  567.  
  568.         } /* while n */
  569.     }
  570.     
  571.     ExitErr(err);
  572.     
  573.     return result;
  574. }
  575.  
  576. static int fs_MBflush( int fd )
  577. {
  578.     OSErr        err = noErr;
  579.     long        count = 0, written = 0;
  580.     char        *bstart;
  581.     int            result = 0;
  582.     
  583.     if ( fd_table[fd].blen <= 0 )
  584.         return 0;
  585.                     
  586.     bstart = fd_table[fd].buffer;
  587.     fd_table[fd].bstart = fd_table[fd].buffer;
  588.     
  589.     if ( fd_table[fd].deof == 0 )
  590.     {    
  591.         written = fd_table[fd].pos - 128L - (long) fd_table[fd].blen;
  592.         count = ( fd_table[fd].rdlen - written );
  593.         /*
  594.          * so count is the number of df bytes still not written to file
  595.          */
  596.          
  597.         if ( count <= (long)fd_table[fd].blen )
  598.         {
  599.             fd_table[fd].blen -= (int)count;
  600.             bstart += count;
  601.             result += (int) count;
  602.             
  603.             count -= (fd_table[fd].rdlen - fd_table[fd].start.dlen);
  604.             if ( count > 0 )
  605.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  606.  
  607.             fd_table[fd].deof = 1;
  608.         }
  609.         else
  610.         {
  611.             count = (long)fd_table[fd].blen;
  612.             fd_table[fd].blen -= (int)count;
  613.             bstart += count;
  614.             result += (int) count;
  615.             
  616.             if ( (written + count) > fd_table[fd].start.dlen )
  617.                 count = fd_table[fd].start.dlen - written;
  618.                 
  619.             if ( count > 0 )    
  620.                 err = FSWrite( fd_table[fd].dref, &count, fd_table[fd].buffer );
  621.         }
  622.         
  623.         if ( noErr != err )
  624.             return err;
  625.     }
  626.  
  627.     if ( fd_table[fd].blen <= 0 )
  628.         return result;
  629.  
  630.     if ( fd_table[fd].reof == 0 )
  631.     {        
  632.         written = fd_table[fd].pos - 128L - fd_table[fd].rdlen - (long)fd_table[fd].blen;
  633.         count = ( fd_table[fd].rrlen - written);
  634.         
  635.         if (count <= 0)
  636.         {
  637.             /* skip  clen */
  638.             fd_table[fd].pos += (long)fd_table[fd].blen;
  639.             fd_table[fd].blen = 0;
  640.             return (result + fd_table[fd].blen);
  641.         }
  642.         
  643.         /*
  644.          * so count is the number of df bytes still not written to file
  645.          */
  646.          
  647.         if ( count <= fd_table[fd].blen )
  648.         {
  649.             fd_table[fd].blen -= (int)count;
  650.             result += (int) count;
  651.             
  652.             count -= (fd_table[fd].rrlen - fd_table[fd].start.rlen);
  653.             if ( count > 0 )
  654.                 err = FSWrite( fd_table[fd].rref, &count, bstart );
  655.  
  656.             fd_table[fd].reof = 1;
  657.         }
  658.         else
  659.         {
  660.             count = (long)fd_table[fd].blen;
  661.             fd_table[fd].blen -= (int)count;
  662.             result += (int) count;
  663.             
  664.             if ( (written + count) > fd_table[fd].start.rlen )
  665.                 count = fd_table[fd].start.rlen - written;
  666.                 
  667.             if ( count > 0 )    
  668.                 err = FSWrite( fd_table[fd].rref, &count, bstart );
  669.         }
  670.         
  671.         if ( noErr != err )
  672.             return err;
  673.     }
  674.     
  675.     return result;
  676. }
  677.  
  678.  
  679. /* ejo: swap '\r' and '\n' for text files (MPW and CW). Note that we */
  680. /* cannot use '\r' and '\n' directly, they have value 0xd and 0xa for */
  681. /* CW and the opposite for MPW (brain damage all over) */
  682.  
  683. static int MyBlockMove( char *src, char *dst, Size n, char c1, char c2 )
  684. {
  685.     char            *tp;
  686.  
  687.     for(    tp = src + n ; src < tp ; src ++ )
  688.             *dst++ = ( *src == c1 ? c2 : *src );
  689.     return 0;
  690. }
  691.  
  692.  
  693. static OSErr    OpenPlainFromMB( int fd )
  694. {
  695.     OSErr        err = noErr;
  696.     long        count = 0;
  697.     
  698.     
  699.     
  700.     if ( fd_table[fd].fsomode & OM_TEXT ) fd_table[fd].mode = MIO_ASCII;
  701.     else fd_table[fd].mode = MIO_BINARY;
  702.     
  703.     
  704.     
  705. /* macgzip -> */
  706.     if ( decompress )
  707.     {
  708.         err = MakeOFSSpec( &fd_table[fd].fs ,
  709.             fd_table[fd].mode == MIO_ASCII ?  "\pSave text file:" : "\pSave binary file:" );
  710.         ofs = fd_table[fd].fs;
  711.         ExitErr(err); /* OJO */
  712.         SetMMString( "g%szip (%s) %s", decompress ? "un" : "" ,( fd_table[fd].mode == MIO_ASCII ) ? "ASCII" : "bin" , ofname );
  713.     }
  714. /* <- macgzip */
  715.  
  716.     
  717.     if ( noErr != (err = FSpCreate(&fd_table[fd].fs, DefCreator, DefType, 0)))
  718.         return err;
  719.     
  720.     fd_table[fd].new        = 1;
  721.         
  722.     if ( noErr != (err = FSpOpenDF(&fd_table[fd].fs, fsWrPerm, &fd_table[fd].dref)))
  723.     {
  724.         fd_table[fd].dref = 0;
  725.         FSpDelete(&fd_table[fd].fs);
  726.         return err;
  727.     }
  728.     
  729.     count = (long)fd_table[fd].pos;
  730.     
  731.     if (fd_table[fd].mode == MIO_ASCII)
  732.         MyBlockMove( (char *)&fd_table[fd].header, fd_table[fd].buffer, (Size) count, 0x0a, 0x0d );
  733.     else
  734.         BlockMove( &fd_table[fd].header, fd_table[fd].buffer, (Size) count );
  735.  
  736.     
  737.     fd_table[fd].blen = fd_table[fd].pos;
  738.     fd_table[fd].bstart = fd_table[fd].buffer + fd_table[fd].pos ;
  739.     
  740.     return err;
  741. }
  742.  
  743. /*******************************************************************************
  744.  *
  745.  * CatInfoToStat - fill in stat struct from CInfoPBRec struct.
  746.  *
  747.  * RETURNS: always zero.
  748.  * from stat.c, Written 4 Nov 94, Erling Johansen.
  749.  */
  750.  
  751. /*
  752. About this implementation
  753. -------------------------
  754. The stat information does not fit perfectly good for the Mac, we don't
  755. have things like inodes, links, uid's and guids. This implementation
  756. put the following information in the stat fields:
  757.  
  758. st_mode        - S_IFDIR | 0777 for directories
  759.             - S_IFDIR | 0666 for regular files
  760.             - the w bit is cleared for locked files
  761.             - the x bit is set for applications and MPW tools
  762.             - S_IFCHR | 0777 for stdin, stdout and stderr
  763.  
  764. st_ino        - ioDrDir ID for directories, file number for files
  765.             - 0 for stdin, stdout and stderr
  766. st_dev        - the volume reference number, 0 for stdin, stdout and stderr
  767. st_nlink    - always 1
  768. st_uid        - always 0
  769. st_gid        - always 0
  770. st_size        - ioFlLgLen (size of data fork)
  771.             - 0 for directories and stdin, stdout and stderr
  772. st_atime    - ioDrMdDat for dirs, ioFlMdDat for files (modification date)
  773.             - current calendar time for stdin, stdout and stderr
  774. st_mtime    - same as st_atime
  775. st_ctime    - ioDrCrDat for dirs, ioFlCrDat for files (creation date)
  776.             - current calendar time for stdin, stdout and stderr
  777.             
  778. */
  779.  
  780. int fs_stat(FSSpec *fs, struct stat *buf)
  781. {
  782.     CInfoPBRec info;
  783.     int err;
  784.     
  785.     info.hFileInfo.ioNamePtr                = fs->name;
  786.     info.hFileInfo.ioVRefNum                 = fs->vRefNum;
  787.     info.hFileInfo.ioFDirIndex                = 0;
  788.     info.hFileInfo.ioDirID                    = fs->parID;
  789.  
  790.  
  791.     if ( noErr != ( err = PBGetCatInfo( (CInfoPBPtr) &info, false ) ) )
  792.         errno = err;
  793.     else if (buf == NULL)
  794.         errno = EFAULT;
  795.     else
  796.         return CatInfoToStat (&info, buf);
  797.         
  798.     return -1;
  799. }
  800.  
  801. static int CatInfoToStat (CInfoPBRec *info, struct stat *buf)
  802. {
  803.     buf->st_nlink = 1;
  804.     buf->st_uid = 0;
  805.     buf->st_gid = 0;
  806.     
  807.     if (info->dirInfo.ioFlAttrib & ioDirMask)
  808.     {
  809.         /* a directory */
  810.         buf->st_mode = S_IFDIR | 0777;
  811.         buf->st_ino = info->dirInfo.ioDrDirID;
  812.         buf->st_dev = info->dirInfo.ioVRefNum;
  813.         buf->st_size = 0;
  814.         buf->st_atime = info->dirInfo.ioDrMdDat;
  815.         buf->st_mtime = info->dirInfo.ioDrMdDat;
  816.         buf->st_ctime = info->dirInfo.ioDrCrDat;
  817.     }
  818.     else
  819.     {
  820.         /* a file */
  821.         buf->st_mode = S_IFREG | 0777;
  822.         
  823.         if (info->hFileInfo.ioFlAttrib & 0x01)
  824.             buf->st_mode &=    ~0222;
  825.  
  826.         if (info->hFileInfo.ioFlFndrInfo.fdType != 'APPL'
  827.             && info->hFileInfo.ioFlFndrInfo.fdType != 'MPST')
  828.             buf->st_mode &=    ~0111;
  829.             
  830.         buf->st_ino = info->hFileInfo.ioDirID;
  831.         buf->st_dev = info->hFileInfo.ioVRefNum;
  832.         buf->st_size = info->hFileInfo.ioFlLgLen;
  833.         buf->st_atime = info->hFileInfo.ioFlMdDat;
  834.         buf->st_mtime = info->hFileInfo.ioFlMdDat;
  835.         buf->st_ctime = info->hFileInfo.ioFlCrDat;
  836.         
  837.         buf->st_dsize = info->hFileInfo.ioFlLgLen;
  838.         buf->st_rsize = info->hFileInfo.ioFlRLgLen;
  839.  
  840.         if ( 0 != (buf->st_dsize%128))
  841.                 buf->st_dsize = buf->st_dsize + ( 128 - buf->st_dsize%128 );
  842.         if ( 0 != (buf->st_rsize%128))
  843.                 buf->st_rsize = buf->st_rsize + ( 128 - buf->st_rsize%128 );
  844.         
  845.         buf->st_mbsize = 128 + buf->st_dsize + buf->st_rsize;
  846.  
  847.     }
  848.             
  849.     return 0;
  850. }
  851.  
  852. static void SanitizeName (Str255 name)
  853. {
  854.     int i;
  855.  
  856.     for( i = 1 ; i <= name[0]; i++ )
  857.         if (( name[i] == 0x00 ) ||  ( name[i] == ':' ))
  858.                 name[i] = '-';
  859.                 
  860.     if (( name[0] > 0) && (name[1] == '.'))
  861.         name[1] = '•';
  862. }
  863.